package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.pojos.CommentVo;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.message.HotArticleConstants;
import com.heima.feigns.user.UserFeign;
import com.heima.model.app.UpdateArticleMess;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    GreenTextScan greenTextScan;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    CommentHotService commentHotService;
    private final Integer size = 10;
    @Autowired
    KafkaTemplate kafkaTemplate;

    /**
     * 评论列表展示
     *
     * @param commentDto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDto commentDto) {
        //1.参数校验
        if (commentDto == null || commentDto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (commentDto.getMinDate() == null) {
            commentDto.setMinDate(new Date());
        }
        //热点评论列表
        List<ApComment> apCommentList = new ArrayList<>();
        if (commentDto.getIndex() == 1) {   //第一页
            //获取热点评论列表
            apCommentList = mongoTemplate.find(Query.query(Criteria.where("entryId").is(commentDto.getArticleId())
                    .and("type").is(0)
                    .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"))
                    .limit(5), ApComment.class);
            if (apCommentList != null && apCommentList.size() > 0) {//有热点评论时
                int hotSize = size - apCommentList.size();
                List<ApComment> CommentList = mongoTemplate.find(Query.query(Criteria.where("entryId").is(commentDto.getArticleId())
                        .and("createdTime").lt(commentDto.getMinDate())
                        .and("type").is(0)
                        .and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))//排序
                        .limit(hotSize), ApComment.class);//每页大小
                apCommentList.addAll(CommentList);
            } else { //没有热点评论时
                apCommentList = mongoTemplate.find(Query.query(Criteria.where("entryId").is(commentDto.getArticleId())
                        .and("createdTime").lt(commentDto.getMinDate())
                        .and("type").is(0)
                        .and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))//排序
                        .limit(size), ApComment.class);//每页大小

            }
        }else { //不是第一页
            //2.根据文章id查询所有评论
            apCommentList = mongoTemplate.find(Query.query(Criteria.where("entryId").is(commentDto.getArticleId())
                    .and("createdTime").lt(commentDto.getMinDate())
                    .and("type").is(0)
                    .and("flag").is(0))
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"))//排序
                    .limit(size), ApComment.class);//每页大小

        }
        if (apCommentList == null || apCommentList.size() == 0) {
            return ResponseResult.okResult();
        }
        //3.用户登录状态

        ApUser apUser = AppThreadLocalUtils.getUser();
        //4.未登录
        if (apUser == null) {
            return ResponseResult.okResult(apCommentList);
        }
        //5.登录
        //所有评论id
        List<String> idList = apCommentList.stream().map(apComment -> apComment.getId())
                .collect(Collectors.toList());
        //查询当前评论下的点赞列表
        List<ApCommentLike> apCommentLikeList = mongoTemplate.find(Query.query(Criteria.where("commentId").in(idList)
                .and("operation").is(0)
                .and("authorId").is(apUser.getId())), ApCommentLike.class);

        //封装返回
        List<CommentVo> commentVoList = new ArrayList<>();
        if (apCommentList != null && apCommentList.size() > 0 && apCommentLikeList != null && apCommentLikeList.size() > 0) {
            apCommentList.forEach(apComment -> {   //所有评论
                CommentVo commentVo = new CommentVo();
                BeanUtils.copyProperties(apComment, commentVo);
                apCommentLikeList.forEach(apCommentLike -> {
                    if (apComment.getId().equals(apCommentLike.getCommentId())) {

                        commentVo.setOperation((short) 0); //当前已点赞的评论回显
                    }
                });
                commentVoList.add(commentVo);
            });

        } else {   //对当前文章评论未点赞
            return ResponseResult.okResult(apCommentList);
        }
        return ResponseResult.okResult(commentVoList);
    }

    /**
     * 给评论点赞和取消点赞
     *
     * @param commentLikeDto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto commentLikeDto) {
        //1.参数校验
        if (commentLikeDto == null || commentLikeDto.getCommentId() == null || commentLikeDto.getOperation() < 0 || commentLikeDto.getOperation() > 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.用户是否登录
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.当前评论是否存在
        ApComment apComment = mongoTemplate.findById(commentLikeDto.getCommentId(), ApComment.class);
        if (apComment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //4.评论点赞行为
        //是否已点赞
        Query query = Query.query(Criteria.where("authorId").is(apUser.getId())
                .and("commentId").is(commentLikeDto.getCommentId()));
        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
        if (apCommentLike != null && commentLikeDto.getOperation() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "已点赞");
        }
        if (commentLikeDto.getOperation() == 0) {
            //点赞
            ApCommentLike commentLike = new ApCommentLike();
            commentLike.setAuthorId(apUser.getId());
            commentLike.setCommentId(commentLikeDto.getCommentId());
            commentLike.setOperation(commentLikeDto.getOperation());
            mongoTemplate.save(commentLike);
            //评论的点赞数+1
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);
            //******计算热点评论（异步）
            if (apComment.getLikes() >= 5 && apComment.getFlag() == 0) {
                log.info("****开始计算热点评论");
                commentHotService.hotCommentExecutor(apComment.getEntryId(), apComment);
            }
        } else {
            //取消点赞
            mongoTemplate.remove(Query.query(Criteria.where("authorId").is(apUser.getId())
                    .and("commentId").is(commentLikeDto.getCommentId())), ApCommentLike.class);
            //评论中打完点赞数—1
            apComment.setLikes((apComment.getLikes() - 1 < 0) ? 0 : apComment.getLikes() - 1);
            mongoTemplate.save(apComment);
        }

        //5.返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 保存评论
     *
     * @param commentSaveDto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto commentSaveDto) {
        //1.参数校验
        if (commentSaveDto == null || commentSaveDto.getArticleId() == null || StringUtils.isBlank(commentSaveDto.getContent()) || commentSaveDto.getContent().length() > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前评论信息非法");
        }
        //2.用户是否登录
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.获取用户对象
        apUser = userFeign.findUserById(apUser.getId());
        if (apUser == null || apUser.getStatus() == 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "当前用户非法");

        }
        //4.评论内容审核（阿里云）
        try {
            Map map = greenTextScan.greenTextScan(commentSaveDto.getContent());
            if (!map.get("suggestion").equals("pass")) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前评论信息不合规");
            }
        } catch (Exception e) {
            log.info("阿里云内容反垃圾审核失败");
        }

        //5.封装数据，保存评论
        ApComment apComment = ApComment.builder()
                .authorId(apUser.getId())
                .authorName(apUser.getName())
                .entryId(commentSaveDto.getArticleId())
                .type((short) 0)
                .content(commentSaveDto.getContent())
                .image(apUser.getImage())
                .likes(0)
                .reply(0)
                .flag(0)
                .createdTime(new Date())
                .build();
        mongoTemplate.save(apComment);
        //实时计算文章分值
        UpdateArticleMess mess = new UpdateArticleMess();
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        mess.setArticleId(commentSaveDto.getArticleId());
        kafkaTemplate.send(HotArticleConstants.HOTARTICLE_SCORE_INPUT_TOPIC, JSON.toJSONString(mess));
        log.info("*****kafkaTemplate send comment ");

        //6.返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
